﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using OrganizedConfusion.Game_Objects;
using System.Collections.Generic;

namespace OrganizedConfusion
{
    public class CameraClass
    {
        public CameraClass(Viewport viewport)
        {
            Port = viewport;
            Origin = new Vector2(viewport.Width * 0.5f, viewport.Height * 0.5f);
            Zoom = 1.0f;
            Rotation = 0.0f;
            PortID = 0;
            Position = new Vector2(viewport.X, viewport.Y);
            LockCamera = false;
        }

        public Vector2 Position { get; set; }
        public Vector2 Origin { get; set; }
        public Viewport Port { get; set; }
        public int PortID { get; set; }
        public bool LockCamera { get; set; }
        private float zoom;
        public float Zoom 
        {
            get { return zoom; }
            set { zoom = value; if (zoom < 0.1f) zoom = 0.1f; }
        }

        public void UpdatePort(Viewport port)
        {
            Origin = new Vector2(port.Width * 0.5f, port.Height * 0.5f);
            Port = port;
        }

        public float Rotation { get; set; }

        public void Update(Player player)
        {
            if (!LockCamera)
            {
                if (!player.GetFacing())
                {
                    //if (player.Position.X > (Origin.X * 0.5f) + Position.X)
                    //    Position = new Vector2((player.Position.X - (Origin.X * 0.5f)) + 5, (player.Position.Y + player.Image.Height) - (Origin.Y + (Origin.Y * 0.5f)));
                    //else
                    Position = new Vector2(player.Position.X - (Origin.X * 0.4f), (player.Position.Y + player.ImageDimensions.Y) - (Origin.Y + (Origin.Y * 0.5f)));
                }
                else
                {
                    //if ((player.Position.X + player.Image.Width) < (Origin.X + (Origin.X * 0.5f)) + Position.X)
                    //    Position = new Vector2((player.Position.X + player.Image.Width) - (Origin.X + (Origin.X * 0.5f)) - 5, (player.Position.Y + player.Image.Height) - (Origin.Y + (Origin.Y * 0.5f)));
                    //else
                    Position = new Vector2((player.Position.X + player.ImageDimensions.X) - (Origin.X + (Origin.X * 0.4f)), (player.Position.Y + player.ImageDimensions.Y) - (Origin.Y + (Origin.Y * 0.4f)));
                }
            }
        }

        public Matrix GetViewMatrix(Vector2 parallax)
        {
            // To add parallax, simply multiply it by the position
            return Matrix.CreateTranslation(new Vector3(-Position * parallax, 0.0f)) *
                // The next line has a catch. See note below.
                   Matrix.CreateTranslation(new Vector3(-Origin, 0.0f)) *
                   Matrix.CreateRotationZ(Rotation) *
                   Matrix.CreateScale(Zoom, Zoom, 1) *
                   Matrix.CreateTranslation(new Vector3(Origin, 0.0f));
        }
    }

    public class CameraManager
    {
        public bool IsHorizontal { get; set; }
        public int Number_Of_Cameras;
        private List<CameraClass> CameraList;
        private Viewport DefaultPort;
        private float ZoomVal;

        public Viewport GetDeafultPort { get { return DefaultPort; } }

        public CameraManager(Viewport viewport)
        {
            DefaultPort = viewport;
            IsHorizontal = false;
            Number_Of_Cameras = 0;
            ZoomVal = 1.0f;
            CameraList = new List<CameraClass>();
        }

        public CameraClass GetCamera(int index)
        {
            if (index > CameraList.Count - 1)
                return null;

            return CameraList[index]; 
        }

        public CameraClass GetCameraByPortID(int ID)
        {
            foreach (CameraClass cam in CameraList)
            {
                if (cam.PortID == ID)
                    return cam;
            }
            return null;
        }

        public Viewport GetViewPort(int index) { return CameraList[index].Port; }

        public void RemoveCamera(int index)
        {
            if (index > CameraList.Count - 1 || index < 0)
                return;

            CameraList.RemoveAt(index);
            Number_Of_Cameras--;
        }

        public void RemoveAll()
        {
            for(int i = 0; i < CameraList.Count;)
                CameraList.RemoveAt(CameraList.Count - 1);

            Number_Of_Cameras = 0;
        }

        /// <summary>
        /// Obsolete camera adding
        /// </summary>
        /// <param name="port"></param>
        public void AddCamera(Viewport port)
        {
            if (Number_Of_Cameras > 3)
                return;

            CameraClass TempCam = new CameraClass(port);

            CameraList.Add(TempCam);
            Number_Of_Cameras++;
        }

        public void AddCamera()
        {
            if (Number_Of_Cameras > 3)
                return;

            switch (Number_Of_Cameras)
            {
                case 0:
                    {
                        Viewport tempPort = DefaultPort;
                        CameraClass TempCam = new CameraClass(tempPort);
                        TempCam.PortID = CameraList.Count;
                        TempCam.Zoom = ZoomVal;

                        CameraList.Add(TempCam);
                        Number_Of_Cameras++;
                        break;
                    }
                case 1:
                    {
                        ZoomVal = 0.75f;
                        Viewport tempPort, tempPort2;
                        tempPort = tempPort2= DefaultPort;
                        if (!IsHorizontal)
                        {
                            tempPort.Width = (int)(tempPort.Width * .5f);
                            tempPort2.Width = (int)(tempPort2.Width * .5f);
                            tempPort2.X = tempPort.Width;
                        }
                        else
                        {
                            tempPort.Height = (int)(tempPort.Height * .5f);
                            tempPort2.Height = (int)(tempPort2.Height * .5f);
                            tempPort2.Y = tempPort.Height;
                        }

                        if (CameraList[0].PortID == 0)
                        {
                            CameraList[0].UpdatePort(tempPort);
                            CameraList[0].Zoom = ZoomVal;
                            CameraClass TempCam = new CameraClass(tempPort2);
                            TempCam.PortID = CameraList.Count;
                            TempCam.Zoom = ZoomVal;

                            CameraList.Add(TempCam);
                        }
                        else
                        {
                            CameraList[0].UpdatePort(tempPort2);
                            CameraList[0].Zoom = ZoomVal;
                            CameraClass TempCam = new CameraClass(tempPort);
                            TempCam.PortID = CameraList.Count-1;
                            TempCam.Zoom = ZoomVal;

                            CameraList.Insert(0, TempCam);
                        }
                        
                        Number_Of_Cameras++;
                        break;
                    }
                case 2:
                    {
                        ZoomVal = 0.5f;
                        Viewport tempPort, tempPort2, tempPort3;
                        tempPort = tempPort2 = tempPort3 = DefaultPort;

                        tempPort.Width = (int)(tempPort.Width * .5f);
                        tempPort2.Width = (int)(tempPort2.Width * .5f);
                        tempPort3.Width = (int)(tempPort3.Width * .5f);

                        tempPort.Height = (int)(tempPort.Height * .5f);
                        tempPort2.Height = (int)(tempPort2.Height * .5f);
                        tempPort3.Height = (int)(tempPort3.Height * .5f);

                        tempPort2.X = tempPort.Width;
                        tempPort3.Y = tempPort.Height;


                        if (CameraList[0].PortID == 0)
                        {
                            if (CameraList[1].PortID == 1)
                            {
                                CameraList[0].UpdatePort(tempPort);
                                CameraList[0].Zoom = ZoomVal;
                                CameraList[1].UpdatePort(tempPort2);
                                CameraList[1].Zoom = ZoomVal;
                                CameraClass TempCam = new CameraClass(tempPort3);
                                TempCam.PortID = CameraList.Count;
                                TempCam.Zoom = ZoomVal;

                                CameraList.Add(TempCam);
                            }
                            else
                            {
                                // Don't update the fourth port if your adding a 3rd viewport.
                                // Prevents the fourth window from moving.
                                //if (CameraList[1].PortID != 3)
                                //    CameraList[1].UpdatePort(tempPort3);

                                CameraList[0].UpdatePort(tempPort);
                                CameraList[0].Zoom = ZoomVal;

                                CameraClass TempCam = new CameraClass(tempPort2);
                                TempCam.PortID = CameraList.Count - 1;
                                TempCam.Zoom = ZoomVal;
                                //CameraList[1].PortID = CameraList.Count - 1;
                                CameraList.Insert(1, TempCam);
                            }
                        }
                        else
                        {
                            if (CameraList[1].PortID != 3)
                                CameraList[1].UpdatePort(tempPort3);

                            CameraList[0].UpdatePort(tempPort);
                            CameraList[0].Zoom = ZoomVal;

                            CameraClass TempCam = new CameraClass(tempPort);
                            TempCam.PortID = 0;
                            TempCam.Zoom = ZoomVal;
                            //CameraList[1].PortID = CameraList.Count - 1;
                            CameraList.Insert(0, TempCam);
                        }

                        Number_Of_Cameras++;
                        break;
                    }
                case 3:
                    {
                        Viewport tempPort, tempPort2, tempPort3, tempPort4;
                        tempPort = tempPort2 = tempPort3 = tempPort4 = DefaultPort;

                        tempPort.Width = (int)(tempPort.Width * .5f);
                        tempPort2.Width = (int)(tempPort2.Width * .5f);
                        tempPort3.Width = (int)(tempPort3.Width * .5f);
                        tempPort4.Width = (int)(tempPort4.Width * .5f);

                        tempPort.Height = (int)(tempPort.Height * .5f);
                        tempPort2.Height = (int)(tempPort2.Height * .5f);
                        tempPort3.Height = (int)(tempPort3.Height * .5f);
                        tempPort4.Height = (int)(tempPort4.Height * .5f);

                        tempPort2.X = tempPort.Width;
                        tempPort3.Y = tempPort.Height;
                        tempPort4.X = tempPort3.Width;
                        tempPort4.Y = tempPort.Height;


                        if (CameraList[0].PortID == 0)
                        {
                            if (CameraList[1].PortID == 1)
                            {
                                if (CameraList[2].PortID == 2)
                                {
                                    CameraList[2].UpdatePort(tempPort3);
                                    CameraClass TempCam = new CameraClass(tempPort4);
                                    TempCam.PortID = CameraList.Count;
                                    CameraList.Add(TempCam);
                                }
                                else
                                {
                                    CameraList[2].UpdatePort(tempPort4);
                                    CameraClass TempCam = new CameraClass(tempPort3);
                                    TempCam.PortID = CameraList.Count - 1;
                                    //CameraList[2].PortID = CameraList.Count;
                                    CameraList.Insert(2, TempCam);
                                }
                            }
                            else
                            {
                                CameraList[1].UpdatePort(tempPort3);
                                CameraList[2].UpdatePort(tempPort4);
                                CameraClass TempCam = new CameraClass(tempPort2);
                                TempCam.PortID = CameraList.Count - 1;
                                //CameraList[1].PortID = CameraList[2].PortID;
                                //CameraList[2].PortID = CameraList.Count;
                                CameraList.Insert(1, TempCam);
                            }
                        }
                        else
                        {
                            if (CameraList[1].PortID != 3)
                                CameraList[1].UpdatePort(tempPort3);

                            //CameraList[2].UpdatePort(tempPort4);

                            CameraClass TempCam = new CameraClass(tempPort);
                            TempCam.PortID = 0;
                            //CameraList[1].PortID = CameraList.Count - 1;
                            CameraList.Insert(0, TempCam);
                        }
                        
                        Number_Of_Cameras++;
                        break;
                    }
            }


        }

    }
}
